package org.example.testgis.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.example.testgis.entity.PointTest;
import org.example.testgis.mapper.PointTestMapper;
import org.example.testgis.service.IPointTestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestClient;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class PointTestServiceImpl extends ServiceImpl<PointTestMapper, PointTest> implements IPointTestService {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Autowired
    private RestTemplate restTemplate;

    @Value("http://localhost:8081/geoserver")  // 这里注意 geoserver 端口号
    private String geoserverUrl;

    @Value("admin")
    private String geoserverUsername;

    @Value("geoserver")
    private String geoserverPassword;

    @Value("point-temp-workspace")
    private String geoserverWorkspace;

    @Override
    public PointTest selectById(Long id) {
        return baseMapper.selectById(id);
    }

    @Override
    public List<PointTest> selectList(PointTest point) {
        QueryWrapper<PointTest> queryWrapper = new QueryWrapper<PointTest>();
        queryWrapper.select("id,name,geom,st_asgeojson(geom) as geoJson");
        return this.getBaseMapper().selectList(queryWrapper);
    }

    @Override
    public int insertPointTest(PointTest point) {
        return baseMapper.insert(point);
    }

    @Override
    public int updatePointTest(PointTest point) {
        return baseMapper.updateById(point);
    }

    @Override
    public PointTest selectGeomById(Long id) {
        QueryWrapper<PointTest> queryWrapper = new QueryWrapper<PointTest>();
        queryWrapper.select("geom","st_asgeojson(geom) as geoJson");
        queryWrapper.eq("id", id);
        return this.getBaseMapper().selectOne(queryWrapper);
    }

    @Override
    public PointTest findGeoJsonById(Long id) {
        return baseMapper.findGeoJsonById(id);
    }

    private String createTemporaryTable(String tableName) {
        try {
            String sql = String.format(
                    "CREATE TABLE IF NOT EXISTS %s AS SELECT * FROM point_test WHERE 1=0;",
                    tableName
            );
            jdbcTemplate.execute(sql);
            return "临时表" + tableName + "创建成功";
        } catch (Exception e) {
            throw new RuntimeException("创建临时表失败：" + e.getMessage());
        }
    }

    private boolean dropTemporaryTable(String tableName) {
        try {
            String sql = String.format("DROP TABLE IF EXISTS %s", tableName);
            jdbcTemplate.execute(sql);
            return true;
        } catch (Exception e) {
            throw new RuntimeException(String.format("删除临时表'%s'失败", tableName));
        }
    }

    private HttpHeaders createAuthHeaders() {
        HttpHeaders headers = new HttpHeaders();
        String auth = geoserverUsername + ":" + geoserverPassword;
        String encodedAuth = java.util.Base64.getEncoder().encodeToString(auth.getBytes());
        headers.set("Authorization", "Basic " + encodedAuth);
        return headers;
    }

    private void createDatastore(String tableName) {
        String url = String.format("%s/rest/workspaces/%s/datastores",  geoserverUrl, geoserverWorkspace);

        Map<String, Object> dataStoreInfo = new HashMap<>();
        dataStoreInfo.put("name",  tableName + "_store");
        dataStoreInfo.put("type", "PostGIS");

        Map<String, Object> connectionParameters = new HashMap<>();
        connectionParameters.put("host", "localhost");
        connectionParameters.put("port", "5432");
        connectionParameters.put("database", "test");
        connectionParameters.put("user", "postgres");
        connectionParameters.put("passwd", "wangjunzhi");
        connectionParameters.put("dbtype", "postgis");

        dataStoreInfo.put("connectionParameters", connectionParameters);
        Map<String, Object> dataStore = new HashMap<>();
        dataStore.put("dataStore",  dataStoreInfo);

        HttpHeaders headers = createAuthHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<Map<String, Object>> entity = new HttpEntity<>(dataStore, headers);

        restTemplate.postForEntity(url, entity, String.class);
    }

    private boolean publishLayer(String tableName, String layerName) {
        String url = String.format("%s/rest/workspaces/%s/datastores/%s_store/featuretypes",
                geoserverUrl, geoserverWorkspace, tableName);

        Map<String, Object> featureType = new HashMap<>();
        Map<String, Object> featureTypeInfo = new HashMap<>();
        featureTypeInfo.put("name", layerName);
        featureTypeInfo.put("nativeName", tableName);
        featureTypeInfo.put("title", layerName);
        featureTypeInfo.put("srs", "EPSG:4326");

        featureType.put("featureType", featureTypeInfo);

        HttpHeaders headers = createAuthHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<Map<String, Object>> entity = new HttpEntity<>(featureType, headers);

        ResponseEntity<String> response = restTemplate.postForEntity(url, entity, String.class);
        return response.getStatusCode().is2xxSuccessful();
    }

    @Override
    public Map<String, Object> autoPublishLayer(Long id) {
        Map<String, Object> result = new HashMap<>();
        String timestamp = String.valueOf(System.currentTimeMillis());
        String tableName = "temp_" + String.valueOf(id) + "_" + timestamp;
        String layerName = String.valueOf(id) + "_layer_" + timestamp;

        // 查询数据是否为空
        PointTest pointTest = findGeoJsonById(id);
        if (pointTest == null) {
            result.put("success", false);
            result.put("message", String.format("找不到id为'%s'的数据", id));
            return result;
        }

        // 创建临时表
        String createTemporaryTableResult = createTemporaryTable(tableName);
        result.put("creatingTemporaryTableResult", createTemporaryTableResult);

        // 复制数据
        String copyDataSQL = String.format(
                "INSERT INTO %s SELECT * FROM point_test WHERE id = %d",
                tableName, id
        );
        result.put("dataCopied", jdbcTemplate.update(copyDataSQL));

        // 发布到 Geoserver
        createDatastore(tableName);
        boolean success = publishLayer(tableName, layerName);
        if (success) {
            result.put("success", true);
            result.put("message", String.format("id为%d的图层发布成功", id));
            result.put("tmpTable", tableName);
            result.put("workspace", geoserverWorkspace);
            result.put("layerName", layerName);
        } else {
            dropTemporaryTable(tableName);
            result.put("success", false);
            result.put("message", String.format("id为%d的图层发布成功", id));
        }

        return result;
    }
}
